from django.shortcuts import render, HttpResponse
from threading import Thread
# Create your views here.
from luffy_api.utils.common_logger import logger


### 日志测试
def index(request):
    # DEBUG < INFO < WARNING < ERROR < CRITICAL
    logger.debug('debug级别')
    logger.info('info级别')
    logger.warning('warning级别')
    logger.error('error级别')
    logger.critical('CRITICAL级别')
    a = [1, 2, 3]
    print('asdasd')
    print('111')
    b = a[9]
    print(b)
    # 以后想用print的位置，都用logger.info,以后项目上线，
    # 调高日志输出级别，虽然代码中写了日志输出，实际上并不会输出
    return HttpResponse('ok')


### 全局异常测试
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import APIException, ValidationError


class ExceptionTestView(APIView):
    def get(self, request):
        # django异常
        # raise Exception('django异常')

        #
        a = [9, 38, 3]
        print(a[99])
        ## drf 异常
        # raise APIException('drf异常')
        # raise ValidationError('认证失败')
        return Response('ok')


#### 测试自己封装的响应对象
from utils.common_response import APIResponse


class MyResponseView(APIView):
    def get(self, request):
        return APIResponse(result=[{'name': 'lqz', 'price': 19}])


from .models import User
from rest_framework.viewsets import ViewSet, GenericViewSet
from rest_framework.decorators import action
from rest_framework.exceptions import APIException
from .serializer import LoginUserSerializer, LoginUserSMSSerializer, UserRegisterSerializer, UserSmsRegisterSerializer
from libs.send_tx_sms import get_code, send_sms_by_mobile
from django.core.cache import cache
from celery_task.user_task import send_sms
from rest_framework.mixins import CreateModelMixin


class UserView(GenericViewSet, CreateModelMixin):
    serializer_class = LoginUserSerializer

    # ********************************手机号码验证和发送验证码

    # 验证手机号是否存在接口---》get请求---》跟数据库有关系，但不需要序列化----》自动生成路由
    @action(methods=['GET'], detail=False)
    def check_mobile(self, request, *args, **kwargs):
        mobile = request.query_params.get('mobile', None)
        if mobile:
            user = User.objects.filter(mobile=mobile).first()
            if user:
                return APIResponse(msg='手机号存在')
        raise APIException('手机号不存在')

    # 发送短信
    @action(methods=['GET'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        # 前端需要把要发送的手机号传入在地址栏中
        mobile = request.query_params.get('mobile', None)
        code = get_code()  # 把code存起来，放在缓存中
        cache.set('send_sms_code_%s' % mobile, code)
        # 从缓存中取
        # cache.get('send_sms_code_%s' % mobile)

        if mobile:
            # 开启一个线程，执行发送短信
            # t = Thread(target=send_sms_by_mobile, args=[mobile, code])
            # t.start()
            # 提交异步任务---》异步发送
            res = send_sms.delay(mobile, code)
            print(res)
            return APIResponse(msg='短信已经发送')
        raise APIException('手机号没有携带！')

    # ******************************************登录功能***************************
    # 判断登录方式用哪个序列化类
    def get_serializer_class(self):
        if self.action == 'sms_login':
            return LoginUserSMSSerializer
        elif self.action == 'register' or self.action == 'create':
            return UserRegisterSerializer
        elif self.action == 'sms_register':
            return UserSmsRegisterSerializer
        else:
            # return super().get_serializer_class()
            return self.serializer_class

    # 多方式登录接口---->要不要序列化类----->要序列化类----->继承的视图类基类
    # post请求 ------->前端携带的数据
    @action(methods=['POST'], detail=False)
    def mul_login(self, request, *args, **kwargs):
        # # 校验逻辑要写在序列化类中
        # ser = self.get_serializer(data=request.data)
        # # 只要执行它，就会执行字段自己的校验规则，局部钩子，全局钩子，全局钩子（全局钩子中写验证逻辑，生成token的逻辑）
        # ser.is_valid(raise_exception=True)  # 如果校验失败，异常会抛出
        # username = ser.context.get('username')
        # token = ser.context.get('token')
        # icon = ser.context.get('icon')
        # return APIResponse(username=username,token=token,icon=icon)
        return self._common_login(request, *args, **kwargs)

    @action(methods=['POST'], detail=False)
    def sms_login(self, request, *args, **kwargs):
        # 前端传入的格式 {mobile:11111,code:8888}
        # 逻辑在序列化类里面
        return self._common_login(request, *args, **kwargs)

    # 两个登录方式的公共部分
    def _common_login(self, request, *args, **kwargs):
        # 校验逻辑要写在序列化类中
        ser = self.get_serializer(data=request.data)
        # 只要执行它，就会执行字段自己的校验规则，局部钩子，全局钩子，全局钩子（全局钩子中写验证逻辑，生成token的逻辑）
        ser.is_valid(raise_exception=True)  # 如果校验失败，异常会抛出
        username = ser.context.get('username')
        token = ser.context.get('token')
        icon = ser.context.get('icon')
        return APIResponse(username=username, token=token, icon=icon)

    # ************************************注册功能***************************

    # 方式一
    # 自己写的 访问 127.0.0.1：8000/api/v1/user/userinfo/register/   --->post请求即可
    @action(methods=['POST'], detail=False)
    def register(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        # super().create(request,*args,**kwargs)  # 只要这样写，又会走序列化类
        return APIResponse(mag='注册成功')

    # 方式二
    # 不自己写了,只要继承CreateModelMixin，访问：127.0.0.1：8000/api/v1/user/userinfo   --->post请求即可
    # 只要post请求过来就会执行create
    def create(self, request, *args, **kwargs):
        # serializer = self.get_serializer(data=request.data)
        # serializer.is_valid(raise_exception=True)
        # self.perform_create(serializer)
        # headers = self.get_success_headers(serializer.data)
        # 序列化要调用它，只要调用serializer.data ，就会走序列化，只要走序列化，会把create返回的user对象 来使用UserRegisterSerializer类做序列化
        # 序列类中得write_only=True
        # return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
        # return APIResponse(msg='注册成功') #不走序列化了，序列类中得write_only 也就不用了
        super().create(request, *args, **kwargs)

    # 写个短信登录注册接口（只需要传手机号和验证码，生成一个默认密码，以短信形式通知用户）

    # 传入手机号码和验证码（这里是验证码必须比较正确才可以），我们测试默认就是8888，然后写个随机密码，存入数据库，再给用户发个短信
    @action(methods=['GET'], detail=False)
    def sms_register(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return APIResponse(msg='注册成功')

    # 记录三次用户密码修改记录，每次改密码，不能跟之前用过的相同
    def update_password(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return APIResponse(mag='修改成功')


########################redis的使用#############################
# redis的普通链接
# import redis
# class MyRedisView(APIView):
#     def get(self,request):
#         # 访问一次，redis的a1 +1
#         conn = redis.Redis()   # 没有池的方案，来几个请求，就会创建几个链接
#         conn.incrby('a1')
#         return APIResponse()


##### 使用池
# from utils.redis_pool import POOL
# import redis
# class MyRedisView(APIView):
#     def get(self,request):
#         # 访问一次，redis的a1 +1
#         conn = redis.Redis(connection_pool=POOL)   # 没有池的方案，来几个请求，就会创建几个链接
#         conn.incrby('a1')
#         return APIResponse()

#####使用第三方
# from django_redis import get_redis_connection
#
# class MyRedisView(APIView):
#     def get(self,request):
#         # 访问一次，redis的a1 +1
#         conn = get_redis_connection()   # 从连接池中拿出一个连接
#
#         conn.incrby('a1')
#         conn.set('name','yzk')
#         return APIResponse()


#### 测试缓存的使用
from django.core.cache import cache


class MyRedisView(APIView):
    def get(self, request):
        # cache.set('age', 19, 10)  # 现在放在redis中
        l = [1, 'lqz', [1, 3, 4, 5, 6], '彭于晏']
        # conn = get_redis_connection()
        # conn.lpush('l1',[1,2,3])  # 存放json格式字符串。要做序列化

        cache.set('ll1', l)

        return APIResponse()


#############################################################################


####测试celery的使用---》前端发送一个get请求，就异步向banner表中插入一条记录
from celery_task.home_task import add_banner


class CeleryView(APIView):
    def get(self, request):
        # 同步用,不用了
        # add_banner()
        # 异步
        res = add_banner.delay()
        print(res)

        return APIResponse(msg='新增banner的任务已经提交了')


from celery_task.user_task import sckill_goods
from celery_task.celery import app
from celery.result import AsyncResult


class SckillView(APIView):
    def post(self, request, *args, **kwargs):
        name = request.data.get('name')
        # 提交秒杀异步任务
        res = sckill_goods.delay(name)
        print(res)  # 任务的id
        return APIResponse(task_id=str(res))

    def get(self, request, *args, **kwargs):
        task_id = request.GET.get('task_id')
        print('返回的id',task_id)
        a = AsyncResult(id=task_id, app=app)
        if a.successful():  # 正常执行完成
            result = a.get()  # 任务返回的结果
            print('判断',result)    # 返回的是True或者False
            if result:
                return APIResponse(code=100, msg='秒杀成功')
            else:
                return APIResponse(code=101, msg='秒杀失败')
        elif a.status == 'STARTED':
            print('任务已经开始被执行')
            return APIResponse(code=103, msg='还在排队')
        else:
            return APIResponse(code=102, msg='没成功')
